Passed
Push — feature/add-2fa-support ( 23e818...85b1f3 )
by Chris
24:19 queued 11:16
created

helpers.ts ➔ applicationBucket   A

Complexity

Conditions 5

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 14
dl 0
loc 26
rs 9.2333
c 0
b 0
f 0
1
import { Application } from "../../models/types";
2
import { ReviewStatusId } from "../../models/lookupConstants";
3
4
type Bucket = "priority" | "citizen" | "non-citizen" | "unqualified";
5
6
type Category = "primary" | "optional" | "screened-out";
7
8
/**
9
 * Returns true if application has been screened out.
10
 */
11
export function isScreenedOut(application: Application): boolean {
12
  return application.application_review &&
13
    application.application_review.review_status
14
    ? application.application_review.review_status.name === "screened_out"
15
    : false; // non-reviewed applications have not been screened-out yet
16
}
17
18
/**
19
 * Return the bucket this application belongs to. Either:
20
 *  priority
21
 *  citizen
22
 *  secondary
23
 *  unqualified
24
 *
25
 */
26
export function applicationBucket(application: Application): Bucket {
27
  if (!application.meets_essential_criteria) {
28
    if (application.citizenship_declaration.name !== "citizen") {
29
      return "non-citizen";
30
    }
31
    return "unqualified";
32
  }
33
34
  if (application.applicant.user.is_priority) {
35
    return "priority";
36
  }
37
38
  if (application.citizenship_declaration.name === "citizen") {
39
    return "citizen";
40
  }
41
42
  return "non-citizen";
43
}
44
45
/**
46
 * Return the category this application belongs to. Either:
47
 *  primary
48
 *  optional
49
 *  screened-out
50
 * @param {Application} application
51
 */
52
export function applicationCategory(application: Application): Category {
53
  if (isScreenedOut(application)) {
54
    return "screened-out";
55
  }
56
  const bucket = applicationBucket(application);
57
  switch (bucket) {
58
    case "priority":
59
    case "citizen":
60
      return "primary";
61
    case "non-citizen":
62
    case "unqualified":
63
    default:
64
      return "optional";
65
  }
66
}
67
68
function isVet(application: Application): boolean {
69
  return application.veteran_status.name !== "none";
70
}
71
72
/**
73
 * Compare function used for sorting applications
74
 */
75
export function applicationCompare(
76
  first: Application,
77
  second: Application,
78
): number {
79
  // Sort by status in the following order:
80
  // "still_in", "Not Reviewed", "still_thinking", "screened_out",
81
  const score = (application: Application): number => {
82
    switch (
83
      application.application_review
84
        ? application.application_review.review_status_id
85
        : null
86
    ) {
87
      case ReviewStatusId.StillIn:
88
        return 1;
89
      case null:
90
        return 2;
91
      case ReviewStatusId.StillThinking:
92
        return 3;
93
      case ReviewStatusId.ScreenedOut:
94
        return 4;
95
      default:
96
        return 2; // Treat default same as "Not Reviewed"
97
    }
98
  };
99
100
  // Add a preference for veterans within each status group
101
  const scoreVet = (application: Application): number =>
102
    score(application) - (isVet(application) ? 0.1 : 0);
103
  const scoreDiff = scoreVet(first) - scoreVet(second);
104
105
  if (scoreDiff !== 0) {
106
    return scoreDiff;
107
  }
108
109
  // Otherwise, sort alphabetically by name;
110
  return first.applicant.user.last_name.localeCompare(
111
    second.applicant.user.last_name,
112
  );
113
}
114
115
/**
116
 * Compare function used for sorting applications, which prioritizes veterans over all others.
117
 */
118
export function applicationComparePrioritizeVeterans(
119
  first: Application,
120
  second: Application,
121
): number {
122
  // Veterans come before others
123
  if (isVet(first) && !isVet(second)) {
124
    return -1;
125
  }
126
  if (!isVet(first) && isVet(second)) {
127
    return 1;
128
  }
129
  return applicationCompare(first, second);
130
}
131